# -*- coding: utf-8 -*-
#
# fusion.tracker.Island
#
# Copyright 2007 Helsinki Institute for Information Technology
# and the authors.
#
# Authors: Toni Ruottu <toni.ruottu@iki.fi>
#          Harri Hämäläinen <harri.hamalainen@helsinki.fi>

# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

'''
Handle URLs of the form "/island/([0-9a-f]{40})/(.*)".
'''

import datetime
import simplejson
import web
import os
from cgi import parse_qs
from sha import sha
from fusion.db.db import hex_to_bytes, bytes_to_hex
from fusion.http.util import withdb
from fusion.tracker.Coast import Coast
from fusion.tracker.pybencode import PyBencode
from fusion.tracker.Tracker_collection import Tracker_collection

class Island(Coast):
    @withdb
    def GET(self, db, collection, request=''):

        input = web.input(output='', timeout='')

        timeout = None
        block = True
        
        if input.timeout:
            try:
                timeout = float(input.timeout)
                block = (timeout > 0)
            except ValueError:
                return web.badrequest()

        try:
            db.keys(collection,
                    autoimport = True,
                    block = block,
                    timeout = timeout)
        except NoSuchCollection:
            return web.notfound()

        if request == 'feed':
            self.feed(collection)

        if request == 'status':
            self.status(collection)

        if request == 'publish':
            self.publish(collection)

        if request == 'hash':
            i = bytes_to_hex(sha(web.input(string='').string).digest())
            web.output(i)

        return

    @withdb
    def feed(self, db, island):

        self.feedi((island,), db.get(island, 'info/title'))

    @withdb
    def status(self, db, collection):
        tracker = Tracker_collection(collection)

        published = tracker.published(db)
        
        requested = set(web.input(info_hash=[]).info_hash)


        if requested:
            requested = requested & published
        else:
            requested = published

        files = {}

        for info_hash in requested:

            file_info = {}

            peers = tracker.discover(db,hex_to_bytes(info_hash))
            complete = tracker.count_seeds(peers)

            file_info['complete'] = complete
            file_info['incomplete'] = len(peers) - complete

            tracker = Tracker_collection(collection)
            file_info['downloaded'] = tracker.count_completed(db, hex_to_bytes(info_hash))

            torrents = db.keys(collection, 'island/'+info_hash+'/file/')
            #torrentfile = PyBencode().decode(db.get(collection, 'island/'+info_hash+'/file/'+torrents[0]))

            #if torrentfile['info'].has_key("files"):
                #size = 0

                #for index in torrentfile['info']['files']:
                    #size += index['length']

                #file_info['size'] = size

            #else:
                #file_info['size'] = torrentfile['info']['length']
            file_info['size'] = 0
            files[info_hash] = file_info

        response = {}
        response['files'] = files

        json = simplejson.dumps(response)

        web.output(json)

        return

    @withdb
    def publish(self, db, collection):
        input = web.input(path=None,description='')
        _, torrent = os.path.split(input.path)
        file = open(input.path,'r')
        ben = file.read()
        file.close()
        metainfo = PyBencode().decode(ben)
        size = 0
        if metainfo['info'].has_key("files"): 

            for index in metainfo['info']['files']:
                size += index['length']

        else:
            size = metainfo['info']['length']
            
        metainfo['announce'] = 'http://localhost:8080/tracker/' + collection + '/announce'
        metainfo['announce-list'] = [['fusion:///tracker/' + collection + '/announce'],['http://localhost:8080/tracker/' + collection + '/announce']]
        ben = PyBencode().encode(metainfo)
        info = metainfo['info']
        info_hash = sha(PyBencode().encode(info)).digest()
        db.put(collection,'island/' + bytes_to_hex(info_hash) + '/file/' + torrent,ben)

        torrent_info = {}
        now = datetime.datetime(1,1,1).utcnow()
        torrent_info['published'] = now.strftime('%Y-%m-%dT%H:%M:%SZ')
        torrent_info['description'] = input.description
        torrent_info['size'] = size

        profile = db.get_local_info('default_profile')
        publisher = {}
        publisher['profile'] = profile
        publisher['name'] = db.get(profile,'info/title')
        torrent_info['publisher'] = publisher
        json = simplejson.dumps(torrent_info)
        db.put(collection,'island/' + bytes_to_hex(info_hash) + '/info/' + torrent + '/info',json)

        db.add_rights(collection,collection,'','post/tracker/' + bytes_to_hex(info_hash))

        db.add_rights(collection,collection,'','post/island/' + bytes_to_hex(info_hash) + '/info/' + torrent + '/comments')
        db.add_rights(collection,collection,'','post/island/' + bytes_to_hex(info_hash) + '/info/' + torrent + '/tags')

        params = parse_qs(web.ctx.query[1:])

        if 'next' in params:
            url = params['next'][0]
            return web.seeother(url)
